package com.xincredit.data.judgement;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.sql.DataSource;

import org.nutz.dao.Sqls;
import org.nutz.dao.entity.Record;
import org.nutz.dao.impl.NutDao;
import org.nutz.dao.impl.SimpleDataSource;
import org.nutz.dao.sql.Sql;
import org.nutz.json.Json;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;

/** select * from t_sp_judge order by id desc limit 100 */
public class JudgementSplit {
	
	private static final Log LOG = Logs.get();
	public static NutDao baseDao;
	protected static Set<String> reasons = new LinkedHashSet<String>();
	
	private static String DELIMITER_SIGN = "@#$", FIELDS_TERMINATED_SIGN = "\\|!\\?\\|";
	
	static {
		DataSource dataSource = getDS();
		baseDao = new NutDao(dataSource);
		LOG.info("get a new dao:" + baseDao);
		loadReason();
		LOG.info("load reason:" + reasons.size());
		if(reasons.size() == 0) {
			throw new RuntimeException("获取reason失败");
		}
	}
	
	public static void loadReason() {
		Sql sql1 = Sqls.create(" select name from t_sp_reason order by length(name) desc ");
		sql1.setCallback(Sqls.callback.records());
		baseDao.execute(sql1);
		List<Record> reasonList = sql1.getList(Record.class);
		for (Record record : reasonList) {
			String name = record.getString("name");
			reasons.add(name);
		}
	}
	
	public static DataSource getDS() {
		SimpleDataSource ds = new SimpleDataSource();
//		ds.setJdbcUrl("jdbc:mysql://106.75.65.54:4040/spider");
		ds.setJdbcUrl("jdbc:mysql://10.10.172.71:3306/spider");
		ds.setUsername("root");
		ds.setPassword("xsjF@8864");
		return ds;
	}

	public static void main(String[] args) throws Exception {
//		String baseFileDir = "D:/iso/cpws/WENSHU-20190527";
			String baseFileDir = "/ftp/cpws/";
		File file = new File(baseFileDir);
		if(file.isDirectory()) {
			File[] listFiles = file.listFiles();
			for(File f : listFiles) {
				if(f.isFile()) {
					String fileName = f.getName();
					if(fileName.startsWith("WENSHU") && fileName.indexOf("gz") == -1) {
						batchContentBr(f);
					}
				}
			}
		} else {
			batchContentBr(file);
		}
	}

	/** 文书正文有换行 */
	public static void batchContentBr(File f) {
		String fileName = f.getName();
		LOG.info("start read file:" + fileName);
		BufferedReader reader = null;
		String line = null;
		int lineCnt = statLineCnt(f, "（"), readNum = 0;
		try {
			
			//读入数据文件 
			BufferedInputStream fis = new BufferedInputStream(new FileInputStream(f));
			reader = new BufferedReader(new InputStreamReader(fis, "UTF-8"), 5 * 1024 * 1024);// 用5M缓冲读取csv文件
			
			char[] cbuf = new char[1000];
			
			int fromIndex = 0;
			int endIndex = 0;
			String lastString = "";
			
			while (reader.read(cbuf, 0, 1000) != -1) {
				fromIndex = 0;
				String trs = lastString + new String(cbuf);
				
				while ((endIndex = trs.indexOf(DELIMITER_SIGN, fromIndex)) != -1) {
					line = trs.substring(fromIndex, endIndex);
					readNum++;
					if(readNum % 500 == 0) {
						LOG.info("done " + readNum + "/" + lineCnt + "; remain	:" + (lineCnt - readNum) + ";file:" + fileName);
					}
//					parseData(line);
					SpJudge sp = make(line);
//					System.out.println(Json.toJson(sp));
					SpJudge record = process(sp);
					fromIndex = endIndex + DELIMITER_SIGN.length();
				}
				lastString = trs.substring(fromIndex);
				cbuf = new char[1000];
			}
			fis.close();
		} catch (Exception e) {
		}
		LOG.info("end read file:" + fileName);
	}

	/** 解析每行数据的每个字段 */
	private static void parseData(String line) {
		String[] cols = line.split(FIELDS_TERMINATED_SIGN);
		for (int i = 0; i < cols.length; i++) {
			System.out.println(cols[i]);
		}
	}
	
	/** 文书正文没有换行 */
	public static void batchContentNoBr(File f) {
		String fileName = f.getName();
		LOG.info("start read file:" + fileName);
		BufferedReader reader = null;
		String line = null;
		int lineCnt = statLineCnt(f, null), readNum = 0;
		try {
			reader = new BufferedReader(new FileReader(f));
			while ((line = reader.readLine()) != null) {
				readNum++;
				if(readNum % 500 == 0) {
					LOG.info("done " + readNum + "/" + lineCnt + "; remain	:" + (lineCnt - readNum) + ";file:" + fileName);
				}
				SpJudge sp = make(line);
				SpJudge record = process(sp);
//				writer.write(JSON.toJSON(record) + "\r\n");
//				writer.flush();
			}
			reader.close();
//			writer.close();
			LOG.info("finished " + readNum + "/" + lineCnt + ";file:" + fileName);
		} catch (Exception e) {
		}
		LOG.info("end read file:" + fileName);
	}

	private static SpJudge make(String line) {
		SpJudge sp = new SpJudge();
		String[] splits = line.split(FIELDS_TERMINATED_SIGN);
		String caseCode = cleanNull(splits[0]);
		String prov = cleanNull(splits[1]);
		String caseType = cleanNull(splits[2]);
		String courtName = cleanNull(splits[3]);
		String reason = cleanNull(splits[4]);
		String program = cleanNull(splits[5]);
		String judgementType = cleanNull(splits[6]);
		
		String judgeYear = cleanNull(splits[7]);
		String publishDate = cleanNull(splits[8]);
		String judgeDate = cleanNull(splits[9]);
		String litigant = cleanNull(splits[10]);
		String beigao = cleanNull(splits[11]);
		String content = cleanNull(splits[12]);
		if(Strings.isNotBlank(content)) {
			try {				
				content = DeleteHtmlTag.delHTMLTag(content);
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}

		String caseName = "";
		int idx = content.indexOf(judgementType);
		caseName = content.substring(0, idx + judgementType.length());
		sp.setCaseName(caseName);

		sp.setCaseCode(caseCode);
		sp.setCaseCodeOri(caseCode);
		
		sp.setCrawlId(UUID.randomUUID().toString());
		sp.setCaseType(caseType);
		sp.setCourtName(courtName);
		sp.setReason(reason);
		sp.setProgram(program);
		sp.setPublishDate(publishDate);
		sp.setJudgeDate(judgeDate);
		sp.setLitigant(litigant);
		sp.setContent(content);
		return sp;
	}
	
	public static SpJudge process(SpJudge record) {
		if (record != null) {
			try {
				String caseName = record.getCaseName();
				String caseCode = record.getCaseCode();
				String content = record.getContent();

				if(Strings.isNotBlank(content)){
					Map<String, Object> parseData = JudgeParser.parseJudgement("", caseName, caseCode, content, reasons);

					record.setProgram(Strings.sNull(parseData.get("program")));
					if (Strings.isBlank(record.getJudgeDate())) {
						record.setJudgeDate(Strings.sNull(parseData.get("judgeDate")));
					}
					record.setReason(Strings.sNull(parseData.get("reason")));
					record.setCaseType(Strings.sNull(parseData.get("caseType")));

					List<String> judges = (List<String>) parseData.get("judges");
					if (!judges.isEmpty()) {
						record.setJudges(Strings.join(",", Lang.collection2array(judges)));
					}

					List<Map<String, String>> personInfo = (List<Map<String, String>>) parseData.get("personInfo");
					List<SpJudgePerson> jps = new ArrayList<SpJudgePerson>();
					StringBuilder litigant = new StringBuilder();
					for (Map<String, String> person : personInfo) {
						SpJudgePerson jp = new SpJudgePerson();
						jp.setDocId(record.getCrawlId());
						jp.setEntityName(person.get("name"));
						jp.setLawOffice(person.get("lawOffice"));
						jp.setPosition(person.get("position"));
						jp.setStandpoint(person.get("standPoint"));
						jp.setEntityId(person.get("idcard"));
						jps.add(jp);
						if (litigant.length() <= 0) {
							litigant.append(person.get("name"));
						} else {
							litigant.append(",").append(person.get("name"));
						}
					}
					record.setLitigant(litigant.toString());
				}

				record.setUrlId(999L);
				if (record.getCrawlTime() == null) {
					record.setCrawlTime(new Date());
				}

				baseDao.insert(record);
				LOG.debug(" insert into judgement " + record.getCrawlId());

//				record.setContent("");
				return record;
			} catch (Exception e) {
				LOG.warn("save exception " + e.getClass().getName() + ", " + record.getCrawlId(), e);
				LOG.info("json_record " + Strings.brief(Json.toJson(record), 500));
			}
		}
		return null;
	}
	
	private static String cleanNull(String column) {
		column = column.trim();
		if(Strings.isNotBlank(column) && "null".equals(column)) {
			return "";
		}
		return column;
	}
	/** 统计文件总行数 */
	public static int statLineCnt(File file, String lineStart) {
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(file));
			int num = 0;
			String line = null;
			while ((line = br.readLine()) != null) {
				if (Strings.isNotBlank(line)) {
					//使用特定的行起始标识
					if(Strings.isNotBlank(lineStart)) {
						if(line.startsWith(lineStart)) {
							num ++;
						}	
					} else {
						num ++;
					}
				}
			}
			return num;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return 0;
	}
}
